#include "splash.h"

const wchar_t SplashClassName[] = L"SplashWindowClass";

static HBITMAP g_hSplashBMP = nullptr;
static HDC g_hSplashDC = nullptr;
static HDC g_hMemoryDC = nullptr;
static LONG g_BitmapWidth = 628;
static LONG g_BitmapHeight = 888;
static HWND g_hSplashWnd = nullptr;
static UINT_PTR g_TimerId = 0;
static int g_iExitApplication = 0;

#define DEMO_SPLASH_TIME 5000

LRESULT CALLBACK SplashWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    switch (Msg)
    {
    case WM_CLOSE:
        g_iExitApplication = 1;
        KillTimer(g_hSplashWnd, g_TimerId);
        PostQuitMessage(0);
        return 0;

    case WM_TIMER:
        g_iExitApplication = 0;
        KillTimer(g_hSplashWnd, g_TimerId);
        PostQuitMessage(0);
        return 0;

    case WM_ERASEBKGND:
        BitBlt(reinterpret_cast<HDC>(wParam), 0, 0, g_BitmapWidth, g_BitmapHeight, g_hMemoryDC, 0, 0, SRCCOPY);
        break;

    default:
        return (DefWindowProc(hWnd, Msg, wParam, lParam));
    }

    return 0;
}

int ShowSplash(HINSTANCE hInstance, UINT_PTR TimerId, int BitmapId)
{
    g_TimerId = TimerId;
    if (TimerId == 0)
    {
        return 0;
    }

    if (BitmapId == 0)
    {
        return 0;
    }

    g_hSplashBMP = LoadBitmap(hInstance, MAKEINTRESOURCE(BitmapId));
    if (!g_hSplashBMP)
    {
        return 0;
    }

    BITMAP Bitmap;
    if (GetObject(g_hSplashBMP, sizeof(BITMAP), &Bitmap))
    {
        g_BitmapWidth = Bitmap.bmWidth;
        g_BitmapHeight = Bitmap.bmHeight;
    }

    int X = 0;
    int Y = 0;
    RECT DesktopRect;
    if (GetWindowRect(GetDesktopWindow(), &DesktopRect))
    {
        X = (DesktopRect.right - g_BitmapWidth) / 2;
        Y = (DesktopRect.bottom - g_BitmapHeight) / 2;
    }

    WNDCLASSEX splashwc;
    splashwc.cbSize = sizeof(WNDCLASSEX);
    splashwc.style = 0;
    splashwc.lpfnWndProc = SplashWndProc;
    splashwc.cbClsExtra = 0;
    splashwc.cbWndExtra = 0;
    splashwc.hInstance = hInstance;
    splashwc.hIcon = NULL;
    splashwc.hIconSm = NULL;
    splashwc.hCursor = LoadCursor(NULL, IDC_ARROW);
    splashwc.hbrBackground = NULL;
    splashwc.lpszMenuName = NULL;
    splashwc.lpszClassName = SplashClassName;
    if (!RegisterClassEx(&splashwc))
    {
        return 0;
    }

    g_hSplashWnd = CreateWindowEx(
        0,
        SplashClassName,
        L"Splash Screen",
        WS_POPUP,
        X,
        Y,
        Bitmap.bmWidth,
        Bitmap.bmHeight,
        NULL,
        NULL,
        hInstance,
        NULL);

    if (!g_hSplashWnd)
    {
        return 0;
    }

    g_hSplashDC = GetDC(g_hSplashWnd);
    if (!g_hSplashDC)
    {
        return 0;
    }

    g_hMemoryDC = CreateCompatibleDC(g_hSplashDC);
    if (!g_hMemoryDC)
    {
        return 0;
    }

    HGDIOBJ hGdiObj;
    hGdiObj = SelectObject(g_hMemoryDC, g_hSplashBMP);
    if (hGdiObj == NULL)
    {
        return 0;
    }

    ShowWindow(g_hSplashWnd, SW_SHOW);
    if (!UpdateWindow(g_hSplashWnd))
    {
        return 0;
    }

    if (!SetTimer(g_hSplashWnd, g_TimerId, DEMO_SPLASH_TIME, NULL))
    {
        return 0;
    }

    MSG msg;

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return g_iExitApplication;
}

int HideSplash()
{
    if (g_hSplashWnd)
    {
        KillTimer(g_hSplashWnd, g_TimerId);

        if (g_hSplashDC)
        {
            ReleaseDC(g_hSplashWnd, g_hSplashDC);
            g_hSplashDC = nullptr;
        }

        if (g_hMemoryDC)
        {
            ReleaseDC(g_hSplashWnd, g_hMemoryDC);
            g_hMemoryDC = nullptr;
        }

        DestroyWindow(g_hSplashWnd);
        g_hSplashWnd = nullptr;
    }

    if (g_hSplashBMP)
    {
        DeleteObject(g_hSplashBMP);
        g_hSplashBMP = nullptr;
    }

    return 0;
}